package __queue

import (
	"errors"
	"fmt"
	"strings"
)

/**
队列的数组实现
重点:
判断队列是否已满
进队列移动尾指针
出队列移动头指针
*/

// 数组的最大值, 队列只能放 maxsize-1 个
const maxSize = 10

type SqQueue struct {
	data  [maxSize]interface{} // 数组
	front int                  // 头指针
	rear  int                  // 尾指针
}

func NewSqQueue() *SqQueue {
	return &SqQueue{}
}

func (s *SqQueue) EnQueue(e interface{}) int {
	if s.front == (s.rear+1)%maxSize {
		return -1
	}
	s.data[s.rear] = e
	s.rear = (s.rear + 1) % maxSize
	return 0
}

func (s *SqQueue) GetHead() interface{} {
	if s.QueueEmpty() {
		return -1
	}
	return s.data[s.front]
}

func (s *SqQueue) DeQueue() (interface{}, error) {
	if s.QueueEmpty() {
		return -1, errors.New("queue is empty")
	}
	r := s.data[s.front]
	s.front = (s.front + 1) % maxSize
	return r, nil
}

func (s *SqQueue) QueueLength() int {
	return (s.rear - s.front + maxSize) % maxSize
}

func (s *SqQueue) QueueEmpty() bool {
	return s.QueueLength() == 0
}

func (s *SqQueue) ClearQueue() {
	s.front = 0
	s.rear = 0
}

func (s *SqQueue) String() string {
	sb := strings.Builder{}
	// 判断
	if s.rear > s.front {
		for i := s.front; i < s.rear; i++ {
			sb.WriteString(s.data[i].(string))
			if i != s.rear-1 {
				sb.WriteString("->")
			}
		}
	} else if s.rear < s.front {
		for i := s.front; i < maxSize; i++ {
			sb.WriteString(s.data[i].(string))
			sb.WriteString("->")
		}
		for i := 0; i < s.rear; i++ {
			sb.WriteString(s.data[i].(string))
			if i != s.rear-1 {
				sb.WriteString("->")
			}
		}
	}
	return fmt.Sprintf("data=%v, length=%d", sb.String(), s.QueueLength())
}
